---
title: Task inheritance
---

import VersionLabel from '@site/src/components/Docs/VersionLabel';

Unlike other task runners that require the same tasks to be repeatedly defined for _every_ project,
moon uses an inheritance model where tasks can be defined once at the workspace-level, and are then
inherited by _many or all_ projects.

Workspace-level tasks (also known as global tasks) are defined in [`.moon/tasks.yml`][tasks] or
[`.moon/tasks/**/*.yml`][tasks], and are inherited by default. However, projects are able to
include, exclude, or rename inherited tasks using the
[`workspace.inheritedTasks`](../config/project#inheritedtasks) in [`moon.yml`](../config/project).

## Scope by project metadata

By default tasks defined in [`.moon/tasks.yml`][tasks] will be inherited by _all_ projects. This
approach works well when a monorepo is comprised of a single programming language, but breaks down
quickly in multi-language setups.

To support these complex repositories, we support scoped tasks with [`.moon/tasks/**/*.yml`][tasks],
where `*.yml` maps to a project based on a combination of its [language][language], [stack][stack],
[layer][layer], or [tags][tags]. This enables you to easily declare tasks for "JavaScript projects",
"Go applications", "Ruby libraries", so on and so forth.

When resolving configuration files, moon will locate and _shallow_ merge files in the following
order, from widest scope to narrowest scope:

- `.moon/tasks.yml` - All projects.
- `.moon/tasks/<language>.yml` - Projects with a matching [`language`][language] setting.
- `.moon/tasks/<stack>.yml` - Projects with a matching [`stack`][stack] setting.
  <VersionLabel version="1.23.0" />
- `.moon/tasks/<language>-<stack>.yml` - Projects with a matching [`language`][language] and
  [`stack`][stack] settings. <VersionLabel version="1.23.0" />
- `.moon/tasks/<stack>-<layer>.yml` - Projects with matching [`stack`][stack] and [`layer`][layer]
  settings. <VersionLabel version="1.23.0" />
- `.moon/tasks/<language>-<layer>.yml` - Projects with matching [`language`][language] and
  [`layer`][layer] settings.
- `.moon/tasks/<language>-<stack>-<layer>.yml` - Projects with matching [`language`][language],
  [`stack`][stack], and [`layer`][layer] settings. <VersionLabel version="1.23.0" />
- `.moon/tasks/tag-<name>.yml` - Projects with a matching [`tag`][tags].
  <VersionLabel version="1.2.0" />

As mentioned above, all of these files are shallow merged into a single "global tasks" configuration
that is unique per-project. Merging **does not** utilize the [merge strategies](#merge-strategies)
below, as those strategies are only utilized when merging global and local tasks.

> Tags are resolved in the order they are defined in `moon.yml` `tags` setting.

### JavaScript runtimes

Unlike most languages that have 1 runtime, JavaScript has 3 (Node.js, Deno, Bun), and we must
support repositories that are comprised of any combination of these 3. As such, JavaScript (and
TypeScript) based projects have the following additional lookups using
[`toolchain`](../config/project#toolchain) to account for this:

- `.moon/tasks/<toolchain>.yml`
- `.moon/tasks/<toolchain>-<stack>.yml`
- `.moon/tasks/<toolchain>-<layer>.yml`
- `.moon/tasks/<toolchain>-<stack>-<layer>.yml`

For example, `node.yml` would be inherited for Node.js projects, `bun-library.yml` for Bun
libraries, and `deno-application.yml` for Deno applications. While `javascript.yml`,
`typescript-library.yml`, etc, will be inherited for all toolchains.

## Merge strategies

When a [global task](../config/tasks#tasks) and [local task](../config/project#tasks) of the same
name exist, they are merged into a single task. To accomplish this, one of many
[merge strategies](../config/project#options) can be used.

Merging is applied to the parameters [`args`](../config/project#args),
[`deps`](../config/project#deps), [`env`](../config/project#env-1),
[`inputs`](../config/project#inputs), and [`outputs`](../config/project#outputs), using the
[`merge`](../config/project#merge), [`mergeArgs`](../config/project#mergeargs),
[`mergeDeps`](../config/project#mergedeps), [`mergeEnv`](../config/project#mergeenv),
[`mergeInputs`](../config/project#mergeinputs) and [`mergeOutputs`](../config/project#mergeoutputs)
options respectively. Each of these options support one of the following strategy values.

- `append` (default) - Values found in the local task are merged _after_ the values found in the
  global task. For example, this strategy is useful for toggling flag arguments.
- `prepend` - Values found in the local task are merged _before_ the values found in the global
  task. For example, this strategy is useful for applying option arguments that must come before
  positional arguments.
- `preserve` - Preserve the original global task values. This should rarely be used, but exists for
  situations where an inheritance chain is super long and complex, but we simply want to the base
  values. <VersionLabel version="1.29.0" />
- `replace` - Values found in the local task entirely _replaces_ the values in the global task. This
  strategy is useful when you need full control.

All 3 of these strategies are demonstrated below, with a somewhat contrived example, but you get the
point.

```yaml
# Global
tasks:
  build:
    command:
      - 'webpack'
      - '--mode'
      - 'production'
      - '--color'
    deps:
      - 'designSystem:build'
    inputs:
      - '/webpack.config.js'
    outputs:
      - 'build/'

# Local
tasks:
  build:
    args: '--no-color --no-stats'
    deps:
      - 'reactHooks:build'
    inputs:
      - 'webpack.config.js'
    options:
      mergeArgs: 'append'
      mergeDeps: 'prepend'
      mergeInputs: 'replace'

# Merged result
tasks:
  build:
    command:
      - 'webpack'
      - '--mode'
      - 'production'
      - '--color'
      - '--no-color'
      - '--no-stats'
    deps:
      - 'reactHooks:build'
      - 'designSystem:build'
    inputs:
      - 'webpack.config.js'
    outputs:
      - 'build/'
    options:
      mergeArgs: 'append'
      mergeDeps: 'prepend'
      mergeInputs: 'replace'
```

[tags]: ../config/project#tags
[tasks]: ../config/tasks
[language]: ../config/project#language
[stack]: ../config/project#stack
[layer]: ../config/project#layer
